package com.caijinbang.study.config;

import com.caijinbang.study.utils.StringUtil;
import com.caijinbang.study.utils.access.MongoAccess;
import com.google.common.collect.Lists;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.MongoException;
import com.mongodb.ServerAddress;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.util.StringUtils;

import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.List;

/**
 * Mongo配置
 *
 * @author caijb
 * @version 1.0.0
 * @date 2018-05-03 14:42
 */
@Configuration
public class MongoConfiguration {

    public static final String SEPARATOR_SERVERS = ",";
    public static final String SEPARATOR_SERVER = ":";

    /**
     * 用户名
     */
    @Value("${mongo.userName}")
    private String userName;
    /**
     * 密码
     */
    @Value("${mongo.password}")
    private String password;
    /**
     * 数据库名称
     */
    @Value("${mongo.dbName}")
    private String dbName;
    /**
     * 服务
     */
    @Value("${mongo.servers}")
    private String servers;
    /**
     * 别名称
     */
    @Value("${mongo.replicaSetName}")
    private String replicaSetName;

    public MongoConfiguration() {

    }

    /**
     * mongoDb客户端
     *
     * @return
     */
    @Bean
    public MongoClient mongoClient() {
        //新建连接
        MongoCredential mongoCredential = this.newMongoCredential();
        //判断连接是否为空
        return mongoCredential == null ? new MongoClient(this.newServerAddresses(), this.newMongoClientOptions()) : new MongoClient(this.newServerAddresses(), Arrays.asList(new MongoCredential[]{mongoCredential}), this.newMongoClientOptions());
    }

    /**
     * 创建连接
     *
     * @return
     */
    private MongoCredential newMongoCredential() {
        //如果字符串里面的值为null,"","   ",那么返回值为false;否则为true
        if (StringUtils.hasText(userName)) {
            char[] passwordArray = StringUtils.hasText(this.password) ? this.password.toCharArray() : new char[0];
            return MongoCredential.createMongoCRCredential(userName, dbName, passwordArray);
        } else {
            return null;
        }
    }

    /**
     * 多个IP集群配置
     * 获取服务地址集合,多个IP集群配置,用","分割开
     *
     * @return
     */
    private List<ServerAddress> newServerAddresses() {
        List<ServerAddress> serverAddresses = Lists.newArrayList();
        String[] serverArray = StringUtil.split(servers, SEPARATOR_SERVERS);
        for (String serverAddress : serverArray) {
            serverAddresses.add(this.newServerAddress(serverAddress));
        }
        return serverAddresses;
    }

    /**
     * 分离ip和端口
     *
     * @param serverAddress
     * @return
     */
    private ServerAddress newServerAddress(String serverAddress) {
        String[] serverHostAndPort = StringUtil.split(serverAddress, SEPARATOR_SERVER);
        String host = serverHostAndPort[0];
        int port = Integer.parseInt(serverHostAndPort[1]);
        return new ServerAddress(host, port);
    }

    /**
     * 获取mongodb工厂
     *
     * @return
     * @throws MongoException
     * @throws UnknownHostException
     */
    @Bean
    public MongoDbFactory mongoDbFactory(@Qualifier("mongoClient") MongoClient mongoClient) throws MongoException, UnknownHostException {
        return new SimpleMongoDbFactory(mongoClient, dbName);
    }

    /**
     * 获取mongo模板实例
     *
     * @param mongoDbFactory
     * @return
     * @throws MongoException
     * @throws UnknownHostException
     */
    @Bean
    public MongoTemplate mongoTemplate(@Qualifier("mongoDbFactory") MongoDbFactory mongoDbFactory) throws MongoException, UnknownHostException {
        return new MongoTemplate(mongoDbFactory);
    }

    /**
     * 获取mongoAccess入口实例
     *
     * @param mongoTemplate
     * @return
     * @throws UnknownHostException
     */
    @Bean
    public MongoAccess mongoAccess(@Qualifier("mongoTemplate") MongoTemplate mongoTemplate) throws UnknownHostException {
        MongoAccess mongoAccess = new MongoAccess();
        mongoAccess.setMongoTemplate(mongoTemplate);
        return mongoAccess;
    }

    /**
     * mongodb连接参数
     *
     * @return
     */
    private MongoClientOptions newMongoClientOptions() {
        MongoClientOptions.Builder optionBuilder = MongoClientOptions.builder();
        if (StringUtils.hasText(replicaSetName)) {
            optionBuilder.requiredReplicaSetName(replicaSetName);
        }
        return optionBuilder.connectionsPerHost(20)
                .threadsAllowedToBlockForConnectionMultiplier(10)
                .connectTimeout(5000)
                .maxWaitTime(6000)
                .socketKeepAlive(true)
                .socketTimeout(5000)
                .build();
    }

}
